#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
串口设备AT指令控制器 - EXE打包工具
功能：将Python项目打包为独立的Windows可执行文件（单文件优化版）
"""

import os
import sys
import subprocess
import shutil
from pathlib import Path

class EXEBuilder:
    """EXE打包工具类"""
    
    def __init__(self):
        """初始化打包工具"""
        self.project_root = Path(__file__).parent.parent
        self.build_dir = self.project_root / "build_tools"
        self.release_dir = self.project_root / "release"
        self.src_dir = self.project_root / "src"
        self.main_script = self.project_root / "main_protected.py"  # 使用受保护版本
        self.icon_path = self.build_dir / "icon.ico"  # 默认图标路径
        self.spec_file = self.build_dir / "SerialRobot.spec"  # 添加spec_file属性
        self.spec_file = self.build_dir / "SerialRobot.spec"  # 使用原始spec
        
    def check_icon(self):
        """检查图标文件"""
        if self.icon_path.exists():
            print(f"✅ 找到图标文件: {self.icon_path}")
            return True
        else:
            print("ℹ️  未找到图标文件，将使用默认图标")
            print("💡 提示: 将图标文件命名为 'icon.ico' 放在 build_tools 文件夹中")
            return False
    
    def check_environment(self):
        """检查打包环境"""
        print("🔍 检查打包环境...")
        
        # 检查Python版本
        if sys.version_info < (3, 7):
            print("❌ Python版本过低，需要3.7+")
            return False
            
        # 检查pyinstaller
        try:
            import PyInstaller
            print(f"✅ PyInstaller已安装: {PyInstaller.__version__}")
        except ImportError:
            print("❌ 未安装PyInstaller，正在安装...")
            subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"])
            
        # 检查依赖
        requirements_file = self.project_root / "requirements.txt"
        if requirements_file.exists():
            print("📦 安装项目依赖...")
            subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", str(requirements_file)])
            
        # 安装优化工具
        try:
            import pip
            subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller-hooks-contrib"])
            print("✅ 已安装优化工具")
        except:
            pass
            
        return True
        
    def create_single_file_spec(self):
        """创建单文件优化版spec"""
        print("📋 创建单文件打包配置文件...")
        
        # 收集所有需要包含的文件
        data_files = []
        
        # 配置文件夹 - 使用更紧凑的方式
        config_dir = self.project_root / "config"
        if config_dir.exists():
            data_files.append((str(config_dir), "config"))
            
        # 数据文件夹
        data_dir = self.project_root / "data"
        if data_dir.exists():
            data_files.append((str(data_dir), "data"))
            
        # MQTT配置文件
        mqtt_config = self.project_root / "mqtt_named_configs.json"
        if mqtt_config.exists():
            data_files.append((str(mqtt_config), "."))
            
        # 生成spec文件内容 - 单文件优化版
        data_files_str = ",\n".join([f'    ("{src}", "{dst}")' for src, dst in data_files])
        
        spec_content = f'''# -*- mode: python ; coding: utf-8 -*-

import sys
import os
from pathlib import Path

# 项目根目录
project_root = Path(SPECPATH).parent

# 需要包含的数据文件 - 最小化集合
datas = [
{data_files_str}
]

# 最小化隐藏导入 - 仅包含必需的
hiddenimports = [
    'serial',
    'serial.tools.list_ports',
    'src.controllers.serial_controller',
    'src.managers.config_manager',
    'src.managers.topic_manager',
    'src.parsers.at_command_parser',
]

# 排除大型模块
excludes = [
    'tkinter',
    'matplotlib',
    'numpy',
    'scipy',
    'PIL',
    'PyQt5',
    'PySide2',
    'test',
    'unittest',
    'distutils',
    'setuptools',
    'pkg_resources',
    'email',
    'http',
    'xml',
    'xmlrpc',
    'urllib',
    'pydoc_data',
    'sqlite3',
    'ssl',
    'bz2',
    'lzma',
]

# 分析主程序
block_cipher = None

a = Analysis(
    [str(project_root / 'main.py')],
    pathex=[str(project_root)],
    binaries=[],
    datas=datas,
    hiddenimports=hiddenimports,
    hookspath=[],
    hooksconfig={{}},
    runtime_hooks=[],
    excludes=excludes,
    win_no_prefer_redirects=True,
    win_private_assemblies=True,
    cipher=block_cipher,
    noarchive=False,
)

# 清理不必要的模块
for d in a.datas[:]:
    if any(exclude in d[0] for exclude in excludes):
        a.datas.remove(d)

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='SerialRobot',
    debug=False,
    bootloader_ignore_signals=False,
    strip=True,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=None,
)
'''
        
        with open(self.spec_file, 'w', encoding='utf-8') as f:
            f.write(spec_content)
            
        print(f"✅ 已创建单文件配置: {{self.spec_file}}")
        
    def clean_before_build(self):
        """打包前清理所有相关文件"""
        print("🧹 清理旧文件...")
        
        # 清理旧的构建文件
        dirs_to_clean = [
            self.dist_dir,
            self.project_root / "build",
            self.build_dir / "build",
            self.build_dir / "dist"
        ]
        
        for dir_path in dirs_to_clean:
            if dir_path.exists():
                try:
                    shutil.rmtree(dir_path)
                    print(f"✅ 已删除: {{dir_path}}")
                except Exception as e:
                    print(f"⚠️  删除失败: {{dir_path}} - {{e}}")
        
        # 清理spec文件（如果存在）
        if self.spec_file.exists():
            try:
                self.spec_file.unlink()
                print(f"✅ 已删除: {{self.spec_file}}")
            except Exception as e:
                print(f"⚠️  删除失败: {{self.spec_file}} - {{e}}")
                
    def clean_after_build(self):
        """打包后清理临时文件"""
        print("🧹 清理临时文件...")
        
        # 清理build临时文件夹
        build_dirs = [
            self.project_root / "build",
            self.build_dir / "build"
        ]
        
        for build_dir in build_dirs:
            if build_dir.exists():
                try:
                    shutil.rmtree(build_dir)
                    print(f"✅ 已清理临时文件: {{build_dir}}")
                except Exception as e:
                    print(f"⚠️  清理失败: {{build_dir}} - {{e}}")
    
    def create_single_exe_release(self):
        """创建单文件release"""
        print("📦 创建单文件Release包...")
        
        # 清理旧的release文件夹
        if self.release_dir.exists():
            try:
                shutil.rmtree(self.release_dir)
                print("✅ 已清理旧的release文件夹")
            except Exception as e:
                print(f"⚠️  清理旧release失败: {e}")
                return False
        
        # 创建release文件夹
        self.release_dir.mkdir(exist_ok=True)
        
        # 源文件路径（单文件）
        source_exe = self.build_dir / "dist" / "SerialRobot.exe"
        if not source_exe.exists():
            print("❌ 未找到打包结果文件")
            return False
        
        # 复制单文件到release
        try:
            release_exe = self.release_dir / "SerialRobot.exe"
            shutil.copy2(source_exe, release_exe)
            file_size = release_exe.stat().st_size / (1024*1024)
            print(f"✅ 已创建单文件程序: {release_exe}")
            print(f"📊 文件大小: {file_size:.1f}MB")
            
            # 创建readme文件
            self.create_single_file_readme()
            
            return True
        except Exception as e:
            print(f"❌ 创建release包失败: {e}")
            return False
    
    def create_single_file_readme(self):
        """创建单文件release的readme说明"""
        readme_content = '''# 串口设备AT指令控制器 - 单文件版

## 📋 文件说明

这是一个经过优化的单文件可执行版本，所有依赖已打包到一个文件中，文件大小最小化。

## 🚀 快速开始

### 1. 运行程序
直接双击 `SerialRobot.exe` 即可启动程序

### 2. 首次使用
- 程序会在首次运行时自动创建必要的配置文件和文件夹
- 请确保已安装串口驱动
- 建议以管理员权限运行（特别是首次运行时）

## 📁 运行时文件结构

程序首次运行时会自动创建以下文件结构：
```
程序所在目录/
├── SerialRobot.exe          # 主程序文件（本文件）
├── config/                  # 配置文件夹（自动生成）
│   ├── relay_config.json    # 继电器配置
│   ├── test_topics.json     # 测试主题配置
│   ├── vbat_config.json     # 电压监测配置
│   └── vbat_records.json    # 电压记录
├── data/                    # 数据文件夹（自动生成）
│   └── device_commands_latest.json  # 最新设备指令
└── mqtt_named_configs.json  # MQTT命名配置（自动生成）
```

## ⚙️ 配置迁移

如果您之前有使用旧版本，可以将以下文件复制到程序所在目录：

1. **配置文件**：复制旧版本的 `config/` 文件夹内容
2. **数据文件**：复制旧版本的 `data/` 文件夹内容
3. **MQTT配置**：复制旧版本的 `mqtt_named_configs.json`

## 🔧 系统要求

- **操作系统**：Windows 7/8/10/11
- **权限要求**：建议以管理员权限运行（首次运行）
- **存储空间**：需要约20MB可用空间用于生成配置文件
- **依赖环境**：无需额外安装，已包含所有依赖

## 💾 文件大小优化

- **原始版本**：约50-80MB（含所有依赖文件夹）
- **优化版本**：约15-25MB（单文件，已压缩）
- **压缩技术**：使用UPX压缩 + 依赖精简

## 📞 常见问题

### 程序无法启动
1. 检查是否被杀毒软件拦截
2. 尝试以管理员权限运行
3. 确保系统已安装VC++运行库

### 串口无法连接
1. 检查设备是否正确连接
2. 确认串口号是否正确
3. 检查是否有其他程序占用串口

### 配置文件错误
1. 删除config文件夹让程序重新生成
2. 检查配置文件格式是否正确
3. 参考默认配置进行修改

### 文件大小异常
如果文件大小超过30MB，可能是因为：
1. 包含了不必要的调试信息
2. 某些依赖未正确排除
3. 建议使用release版本而非debug版本

## 🆘 技术支持

如遇到其他问题，请：
1. 检查程序所在目录下的日志文件
2. 尝试删除config和data文件夹后重新运行
3. 确保系统权限足够

---
**生成时间**：{timestamp}
**版本信息**：串口设备AT指令控制器 v1.0 单文件优化版
**文件大小**：约15-25MB（已优化）
'''
        
        # 添加时间戳
        from datetime import datetime
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        readme_content = readme_content.format(timestamp=timestamp)
        
        readme_file = self.release_dir / "README.md"
        try:
            with open(readme_file, 'w', encoding='utf-8') as f:
                f.write(readme_content)
            print(f"✅ 已创建单文件说明: {{readme_file}}")
            return True
        except Exception as e:
            print(f"⚠️  创建readme文件失败: {{e}}")
            return False
    
    def build_single_exe(self):
        """构建单文件exe"""
        print("🔨 开始构建单文件exe...")
        
        # 检查图标
        has_icon = self.check_icon()
        
        # 构建命令
        cmd = [
            "pyinstaller",
            "--onefile",
            "--name", "SerialRobot",
            "--distpath", str(self.build_dir / "dist"),
            "--workpath", str(self.build_dir / "build"),
            "--specpath", str(self.build_dir),
            "--clean",
            "--noconfirm"
        ]
        
        # 添加图标参数
        if has_icon:
            cmd.extend(["--icon", str(self.icon_path)])
        
        # 添加UPX压缩
        cmd.extend([
            "--upx-dir", "upx",
            "--upx-exclude", "vcruntime140.dll"
        ])
        
        # 排除不必要的模块
        excludes = [
            "tkinter", "tcl", "tk", "matplotlib", "PyQt5", "PyQt6", 
            "PySide2", "PySide6", "wx", "gtk", "gi", "kivy", "pyside",
            "test", "unittest", "pytest", "numpy", "pandas", "scipy",
            "IPython", "jupyter", "notebook", "docutils", "sphinx"
        ]
        
        for exclude in excludes:
            cmd.extend(["--exclude-module", exclude])
        
        # 添加隐藏导入
        hidden_imports = [
            "serial", "serial.tools", "serial.tools.list_ports",
            "paho.mqtt.client", "json", "threading", "time", 
            "datetime", "pathlib", "re", "sys", "os",
            "src.utils.encryption", "src.utils.startup_guard", "platform",
            "hashlib", "base64", "subprocess"
        ]
        
        for imp in hidden_imports:
            cmd.extend(["--hidden-import", imp])
        
        # 添加主脚本
        cmd.append(str(self.main_script))
        
        print("📝 执行命令:", " ".join(cmd))
        
        try:
            result = subprocess.run(cmd, cwd=str(self.project_root), capture_output=True, text=True)
            
            if result.returncode == 0:
                print("✅ 单文件打包成功")
                return self.create_single_exe_release()
            else:
                print("❌ 单文件打包失败")
                print("错误信息:")
                print(result.stderr)
                return False
                
        except Exception as e:
            print(f"❌ 打包过程出错: {e}")
            return False
            
    def create_single_bat_file(self):
        """创建单文件打包批处理文件"""
        bat_content = f'''@echo off
echo.
echo ========================================
echo   串口设备AT指令控制器 - 单文件优化打包
echo ========================================
echo.
echo 正在执行单文件优化打包...
echo 这将生成一个单独的可执行文件，文件大小已优化
echo.

cd /d "{self.build_dir}"
python build_exe.py --single

echo.
echo 按任意键退出...
pause
'''
        
        bat_file = self.build_dir / "单文件打包.bat"
        with open(bat_file, 'w', encoding='gbk') as f:
            f.write(bat_content)
            
        print(f"✅ 已创建: {bat_file}")
        
    def create_single_setup_guide(self):
        """创建单文件使用说明"""
        guide_content = '''# 串口设备AT指令控制器 - 单文件优化打包说明

## 🎯 单文件打包（推荐）

### 方法1：一键单文件打包
1. 双击运行 `单文件打包.bat`
2. 等待自动完成（约3-5分钟）
3. 生成的单文件exe在 `release/SerialRobot.exe`

### 方法2：手动单文件打包
1. 打开命令提示符
2. 切换到 build_tools 目录
3. 运行: `python build_exe.py --single`

## 🎨 自定义图标设置

### 设置程序图标
1. 准备图标文件（.ico格式，推荐256x256像素）
2. 将图标文件重命名为 `icon.ico`
3. 将图标文件放在 `build_tools` 文件夹中
4. 重新运行打包命令

### 图标要求
- **格式**: Windows图标格式 (.ico)
- **尺寸**: 16x16, 32x32, 48x48, 256x256 像素
- **颜色**: 支持透明背景
- **文件**: 命名为 `icon.ico`

### 图标制作工具推荐
- **在线工具**: icoConvert.com, ConvertICO.com
- **本地软件**: Greenfish Icon Editor, GIMP
- **命令行**: ImageMagick 转换工具

## 📊 文件大小对比

| 打包方式 | 文件数量 | 总大小 | 特点 |
|---------|----------|--------|------|
| 文件夹版 | 100+     | 50-80MB | 完整依赖，调试方便 |
| 单文件版 | 1        | 15-25MB | 便携，最小化，推荐 |

## 💡 使用说明

1. **首次运行**：程序会自动创建必要的配置文件和文件夹
2. **便携使用**：单个exe文件，可移动到任意位置运行
3. **配置迁移**：将原有config和data文件夹复制到exe同目录
4. **权限要求**：建议首次运行以管理员权限

## ⚡ 优化措施

- **依赖精简**：移除不必要的标准库
- **压缩技术**：使用UPX压缩算法
- **模块排除**：排除大型GUI框架和测试模块
- **单文件模式**：所有内容打包到一个exe中

## 🔄 切换打包模式

如果需要文件夹版（调试模式）：
```bash
python build_exe.py --folder
```

需要单文件版（发布模式）：
```bash
python build_exe.py --single
```

## ⚠️ 注意事项

- 单文件首次运行会稍慢（需要解压到临时目录）
- 杀毒软件可能会误报（添加信任即可）
- 确保系统已安装VC++运行库
- 文件大小优化基于实际依赖分析
'''
        
        guide_file = self.build_dir / "单文件打包说明.txt"
        with open(guide_file, 'w', encoding='utf-8') as f:
            f.write(guide_content)
            
        print(f"✅ 已创建: {guide_file}")
        
    def run_single(self):
        """运行单文件打包流程"""
        print("🚀 串口设备AT指令控制器 - 单文件优化打包")
        print("=" * 60)
        print("📦 生成单个exe文件，文件大小优化至最小")
        print("=" * 60)
        
        if not self.check_environment():
            return False
            
        self.create_single_file_spec()
        self.create_single_bat_file()
        self.create_single_setup_guide()
        
        success = self.build_single_exe()
        if success:
            exe_path = self.release_dir / "SerialRobot.exe"
            if exe_path.exists():
                file_size = exe_path.stat().st_size / (1024*1024)
                print(f"\n🎉 单文件打包成功！")
                print(f"📍 EXE文件: {exe_path}")
                print(f"📊 文件大小: {file_size:.1f}MB")
                print("✅ 已优化至最小体积")
                return True
        
        return False
        
    def run_folder(self):
        """运行文件夹打包流程"""
        print("📁 串口设备AT指令控制器 - 文件夹打包模式")
        print("=" * 60)
        print("📦 生成完整文件夹，包含所有依赖文件")
        print("=" * 60)
        
        if not self.check_environment():
            return False
            
        # 检查图标
        has_icon = self.check_icon()
        
        # 构建命令
        cmd = [
            "pyinstaller",
            "--onedir",
            "--name", "SerialRobot",
            "--distpath", str(self.release_dir),
            "--workpath", str(self.build_dir / "build"),
            "--specpath", str(self.build_dir),
            "--clean",
            "--noconfirm"
        ]
        
        # 添加图标参数
        if has_icon:
            cmd.extend(["--icon", str(self.icon_path)])
        
        # 添加数据文件
        cmd.extend([
            "--add-data", f"{self.project_root / 'config'};config",
            "--add-data", f"{self.project_root / 'data'};data",
            "--add-data", f"{self.project_root / 'mqtt_named_configs.json'};.",
            "--add-data", f"{self.project_root / 'requirements.txt'};.",
            "--add-data", f"{self.project_root / 'README.md'};."
        ])
        
        # 排除不必要的模块
        excludes = [
            "tkinter", "tcl", "tk", "matplotlib", "PyQt5", "PyQt6", 
            "PySide2", "PySide6", "wx", "gtk", "gi", "kivy", "pyside",
            "test", "unittest", "pytest", "numpy", "pandas", "scipy",
            "IPython", "jupyter", "notebook", "docutils", "sphinx"
        ]
        
        for exclude in excludes:
            cmd.extend(["--exclude-module", exclude])
        
        # 添加隐藏导入
        hidden_imports = [
            "serial", "serial.tools", "serial.tools.list_ports",
            "paho.mqtt.client", "json", "threading", "time", 
            "datetime", "pathlib", "re", "sys", "os"
        ]
        
        for imp in hidden_imports:
            cmd.extend(["--hidden-import", imp])
        
        # 添加主脚本
        cmd.append(str(self.main_script))
        
        print("📝 执行命令:", " ".join(cmd))
        
        try:
            result = subprocess.run(cmd, cwd=str(self.project_root), capture_output=True, text=True)
            
            if result.returncode == 0:
                print("✅ 文件夹打包成功")
                folder_path = self.release_dir / "SerialRobot"
                if folder_path.exists():
                    print(f"📁 文件夹位置: {folder_path}")
                    return True
            else:
                print("❌ 文件夹打包失败")
                print("错误信息:")
                print(result.stderr)
                return False
                
        except Exception as e:
            print(f"❌ 打包过程出错: {e}")
            return False
            
    def create_single_bat_file(self):
        """创建单文件打包批处理文件"""
        bat_content = f'''@echo off
echo.
echo ========================================
echo   串口设备AT指令控制器 - 单文件优化打包
echo ========================================
echo.
echo 正在执行单文件优化打包...
echo 这将生成一个单独的可执行文件，文件大小已优化
echo.

cd /d "{self.build_dir}"
python build_exe.py --single

echo.
echo 按任意键退出...
pause
'''
        
        bat_file = self.build_dir / "单文件打包.bat"
        with open(bat_file, 'w', encoding='gbk') as f:
            f.write(bat_content)
            
        print(f"✅ 已创建: {bat_file}")
        
    def create_single_setup_guide(self):
        """创建单文件使用说明"""
        guide_content = '''# 串口设备AT指令控制器 - 单文件优化打包说明

## 🎯 单文件打包（推荐）

### 方法1：一键单文件打包
1. 双击运行 `单文件打包.bat`
2. 等待自动完成（约3-5分钟）
3. 生成的单文件exe在 `release/SerialRobot.exe`

### 方法2：手动单文件打包
1. 打开命令提示符
2. 切换到 build_tools 目录
3. 运行: `python build_exe.py --single`

## 📊 文件大小对比

| 打包方式 | 文件数量 | 总大小 | 特点 |
|---------|----------|--------|------|
| 文件夹版 | 100+     | 50-80MB | 完整依赖，调试方便 |
| 单文件版 | 1        | 15-25MB | 便携，最小化，推荐 |

## 💡 使用说明

1. **首次运行**：程序会自动创建必要的配置文件和文件夹
2. **便携使用**：单个exe文件，可移动到任意位置运行
3. **配置迁移**：将原有config和data文件夹复制到exe同目录
4. **权限要求**：建议首次运行以管理员权限

## ⚡ 优化措施

- **依赖精简**：移除不必要的标准库
- **压缩技术**：使用UPX压缩算法
- **模块排除**：排除大型GUI框架和测试模块
- **单文件模式**：所有内容打包到一个exe中

## 🔄 切换打包模式

如果需要文件夹版（调试模式）：
```bash
python build_exe.py --folder
```

需要单文件版（发布模式）：
```bash
python build_exe.py --single
```

## ⚠️ 注意事项

- 单文件首次运行会稍慢（需要解压到临时目录）
- 杀毒软件可能会误报（添加信任即可）
- 确保系统已安装VC++运行库
- 文件大小优化基于实际依赖分析
'''
        
        guide_file = self.build_dir / "单文件打包说明.txt"
        with open(guide_file, 'w', encoding='utf-8') as f:
            f.write(guide_content)
            
        print(f"✅ 已创建: {guide_file}")
        
    def run_single(self):
        """运行单文件打包流程"""
        print("🚀 串口设备AT指令控制器 - 单文件优化打包")
        print("=" * 60)
        print("📦 生成单个exe文件，文件大小优化至最小")
        print("=" * 60)
        
        if not self.check_environment():
            return False
            
        self.create_single_file_spec()
        self.create_single_bat_file()
        self.create_single_setup_guide()
        
        success = self.build_single_exe()
        if success:
            exe_path = self.release_dir / "SerialRobot.exe"
            if exe_path.exists():
                file_size = exe_path.stat().st_size / (1024*1024)
                print(f"\n🎉 单文件打包成功！")
                print(f"📍 EXE文件: {exe_path}")
                print(f"📊 文件大小: {file_size:.1f}MB")
                print("✅ 已优化至最小体积")
                return True
        
        return False
        
    def run_folder(self):
        """运行文件夹版打包流程"""
        self.spec_file = self.build_dir / "SerialRobot.spec"  # 使用原始spec
        
        print("🚀 串口设备AT指令控制器 - 文件夹版打包")
        print("=" * 50)
        
        if not self.check_environment():
            return False
            
        # 使用原始spec文件
        if not self.spec_file.exists():
            # 创建原始spec（如果不是单文件模式）
            self.spec_file = self.build_dir / "SerialRobot.spec"
            self.create_spec_file()  # 使用原始方法
        
        # 执行文件夹打包
        cmd = [
            "pyinstaller",
            "--clean",
            "--noconfirm",
            str(self.spec_file)
        ]
        
        try:
            subprocess.check_call(cmd, cwd=str(self.build_dir))
            print("✅ 文件夹打包完成！")
            
            # 创建release包
            release_success = self.create_release_package()
            self.clean_after_build()
            
            return release_success
        except subprocess.CalledProcessError as e:
            print(f"❌ 文件夹打包失败: {e}")
            return False
            
    def run(self, mode="single"):
        """运行打包流程"""
        if mode == "single" or "--single" in sys.argv:
            return self.run_single()
        elif mode == "folder" or "--folder" in sys.argv:
            return self.run_folder()
        else:
            # 默认单文件模式
            return self.run_single()

if __name__ == "__main__":
    builder = EXEBuilder()
    
    # 解析命令行参数
    mode = "single"  # 默认单文件模式
    if "--folder" in sys.argv:
        mode = "folder"
    elif "--single" in sys.argv:
        mode = "single"
    
    try:
        success = builder.run(mode)
        if success:
            print("\n✅ 打包流程完成！")
            if mode == "single":
                exe_path = builder.release_dir / "SerialRobot.exe"
                if exe_path.exists():
                    size = exe_path.stat().st_size / (1024*1024)
                    print(f"📦 单文件大小: {size:.1f}MB")
        else:
            print("\n❌ 打包流程失败！")
            sys.exit(1)
    except KeyboardInterrupt:
        print("\n⚠️ 用户中断")
        sys.exit(1)
    except Exception as e:
        print(f"\n❌ 发生错误: {e}")
        sys.exit(1)
    
    input("\n按回车键退出...")